﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework.Audio;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Threading;
using System.Threading;
using System.Diagnostics;
using Microsoft.Xna.Framework;

namespace OptymalizatorTrasy
{
    public abstract class Converter
    {
        private ConverterService cv; //stworzenie obiektu do łączenia się z serwisem
        private String mowa; //string do przetrzymywania mowy po zakodowaniu w Base64
        
        //nagrywanie dźwięku
        private Microphone aktualnyMikrofon = null; //aktualny mikrofon do nagrywania
        private bool checZakonczenia = false; //czy została zgłoszona chęć zakończenia nagrywania
        private byte[] audioBuffer; //tablica bytów do przetrzymywania nagranego dźwięku
        private int czestotliwosc; //częstotliwość nagrywanego i odtwarzanego dźwięku
        private MemoryStream aktualnyStrumienNagrywania; //strumień w kórym przechowujemy dźwięk
        private SoundEffectInstance aktualnyDzwiek; //element do odtworzenia naszego dźwięku

        //metody abstrakcyjne TOSĄ TYLKO DO: MOWA NA TEKST, POWINNY BY TEŻ TEKST NA MOWA!!
        abstract public void wykonajAkcjePrzed(); //wykonanie wszystkich czynności przed buforowaniem
        abstract public void wykonajAkcjePo(String tekst);  //wykonanie wszystkich czynności po zamianach

        public Converter()
        {
            cv = new ConverterService(this);
        }

        #region tekstNaMowa
        //zamiana tekstu na mowę -> po zakończeniu zostaje odtworzony dźwięk
        public void tekstNaMowe(String tekst)
        {
            String odpowiedz = cv.tekstNaMowe(tekst); //odwolanie się do naszej aplikacji na serwerze, w odpowiedzi otrzymujemy dźwięk zakodowany w Base64
            odtwarzaj(odpowiedz); 
        }

        //odtwarzanie dźwięku
        private void odtwarzaj(String dzwiekWBase64)
        {
            byte[] odsluch = Convert.FromBase64String(dzwiekWBase64); //odkodowanie naszego dźwięku i zapisanie do tablicy bytów

           // Debug.WriteLine("Wielkosc odsluchu: " + odsluch.Length + "\n");

            if (aktualnyDzwiek != null) //jeśli jest odtwarzane co innego to zatrzymaj
            {
                aktualnyDzwiek.Stop();
                aktualnyDzwiek = null;
            }
            //odtworzenie dźwięku z pliku WAV <- sprawdzenie tylko -- WYKASOWAC POTEM!!!!
         /*   var isoStore = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
            if (isoStore.FileExists("pomocniczy.WAV"))
            {
 
                SoundEffect se;
                using (var fileStream = isoStore.OpenFile("pomocniczy.WAV", FileMode.Open))
                {
                    se = SoundEffect.FromStream(fileStream);
                    fileStream.Close();//not really needed, but it makes me feel better. 
                }

                aktualnyDzwiek = se.CreateInstance();
                aktualnyDzwiek.Play();
            }//a to odkomentować*/

            AudioChannels channels = (odsluch[22] == 1) ? AudioChannels.Mono : AudioChannels.Stereo;
            SoundEffect se = new SoundEffect(odsluch, 44, odsluch.Length - 44, 8000, channels, 0, 0);
            
            aktualnyDzwiek = se.CreateInstance();
            aktualnyDzwiek.Play(); //odtwarzajbo n
        }

        #endregion

        #region mowaNaTekst

        //rozpoczęcie nagrywania 
        public void nagrywaj()
        {
            if (aktualnyMikrofon == null) //jeśli nie ma aktualnego mikrofonu to go definiujemy
            {
                aktualnyMikrofon = Microphone.Default;
                aktualnyMikrofon.BufferReady += new EventHandler<EventArgs>(currentMicrophone_BufferReady); //dodania EventHandlera do mikrofonu

                audioBuffer = new byte[aktualnyMikrofon.GetSampleSizeInBytes(aktualnyMikrofon.BufferDuration)];
                czestotliwosc = aktualnyMikrofon.SampleRate;
            }
            checZakonczenia = false;
            aktualnyStrumienNagrywania = new MemoryStream(1048576);
            aktualnyMikrofon.Start(); //start nagrywania
        }

        //obsługa zapełnienia sie bufora podręcznego
        private void currentMicrophone_BufferReady(object sender, EventArgs e)
        {
            //zapisanie do strumienia danych
            aktualnyMikrofon.GetData(audioBuffer);
            aktualnyStrumienNagrywania.Write(audioBuffer, 0, audioBuffer.Length);
            
            if (!checZakonczenia) return; //jeśli nie chcemy zakończyć to nagrywaj dalej
            
            aktualnyMikrofon.Stop();  //jeśli została zgłoszona chęć zakończenia to zatrzymaj nagrywanie

            //zapisanie do pliku naszego dźwięku
            var isoStore = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();

            using (var targetFile = isoStore.CreateFile("pomocniczy.WAV"))
            {
                WaveHeaderWriter.WriteHeader(targetFile, (int)aktualnyStrumienNagrywania.Length, 1, czestotliwosc);
                var dataBuffer = aktualnyStrumienNagrywania.GetBuffer();
                targetFile.Write(dataBuffer, 0, (int)aktualnyStrumienNagrywania.Length);
                targetFile.Flush();
                targetFile.Close();
            }


            if (isoStore.FileExists("pomocniczy.WAV"))
            {
                SoundEffect se;
                using (var fileStream = isoStore.OpenFile("pomocniczy.WAV", FileMode.Open))
                {
                    byte[] przesyl = new byte[80000];
                    fileStream.Read(przesyl, 0, 80000);
                    mowa = Convert.ToBase64String(przesyl);
                    fileStream.Close();//not really needed, but it makes me feel better. 
                }
            }

          //  Debug.WriteLine("Długość bufora: " + aktualnyStrumienNagrywania.GetBuffer().Length + "\n");
            mowa = Convert.ToBase64String(aktualnyStrumienNagrywania.GetBuffer()); //konwertujemy nasz dźwięk na stringa base64 po to by móc go wysłać do WebSerwera

            Debug.WriteLine("Dlugosc mowy: " + mowa);

            //odtwarzaj(mowa); //WYKASOWAC POZNIEJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            //wykonajAkcjePo("bla");//WYKASOWAC POZNIEJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            cv.mowaNaTekst(mowa); //odwołanie się do naszej aplikacji na serwerze, otrzymanie tekstu

            
 
        }      

        //zgłoszenie chęci zakończenia nagrywania -> w praktyce jeszcze się nagrywa, tak aby uchwycić ostatnią frazę
        public void zakoncz()
        {
            checZakonczenia = true;
            wykonajAkcjePrzed();
        }

        #endregion

    }
}
